#include <cstdio>
#include <cstring>
#include <ctime>
#include <graphics.h>
#include <conio.h>
#include <cstdio>
using namespace std;
const COLORREF BGC = RGB(250, 248, 239);
int score, best, a[5][5], b[5][5];
bool mov[5][5];
void init()
{
    setbkcolor(BGC);
    setbkmode(TRANSPARENT);
    score = 0;
    memset(a, 0, sizeof(a));
    int x1 = rand() % 4 + 1, y1 = rand() % 4 + 1, x2 = rand() % 4 + 1, y2 = rand() % 4 + 1;	// 随机生成两个初始点
    a[x1][y1] = a[x2][y2] = 2;
}
void drawmap()
{
    BeginBatchDraw();
    cleardevice();
    settextcolor(RGB(119, 110, 101));
    settextstyle(50, 0, L"微软雅黑");
    outtextxy(10, 10, L"2048");
    settextstyle(20, 0, L"微软雅黑", 0, 0, 550, false, false, false);
    outtextxy(10, 65, L"Join the numbers and get to the 2048 tile!");
    setfillcolor(RGB(187, 173, 160));
    solidroundrect(200, 15, 290, 60, 5, 5);
    settextcolor(RGB(230, 220, 210));
    settextstyle(15, 0, L"微软雅黑", 0, 0, 600, false, false, false);
    outtextxy(230, 20, L"SCORE");
    wchar_t sc[10] = L"";
    swprintf_s(sc, L"%d", score);
    settextcolor(WHITE);
    settextstyle(25, 0, L"微软雅黑", 0, 0, 600, false, false, false);
    RECT r = { 200, 30, 290, 60 };
    drawtext(sc, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    solidroundrect(295, 15, 385, 60, 5, 5);
    settextcolor(RGB(230, 220, 210));
    settextstyle(15, 0, L"微软雅黑", 0, 0, 600, false, false, false);
    outtextxy(330, 20, L"BEST");
    wchar_t bs[10] = L"";
    swprintf_s(bs, L"%d", best);
    settextcolor(WHITE);
    settextstyle(25, 0, L"微软雅黑", 0, 0, 600, false, false, false);
    r = { 295, 30, 385, 60 };
    drawtext(bs, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
    solidroundrect(10, 90, 390, 470, 5, 5);
    settextstyle(23, 0, L"微软雅黑");
    settextcolor(WHITE);
    for (int i = 1; i <= 4; i++)
        for (int j = 1; j <= 4; j++)
            if (a[i][j])
            {
                setfillcolor(RGB((unsigned int)(BGC - 3 * (a[i][j] ^ 29)) % 256, (unsigned int)(BGC - 11 * (a[i][j] ^ 23)) % 256, (unsigned int)(BGC + 7 * (a[i][j] ^ 37)) % 256));
                solidroundrect(94 * j - 80, 94 * i, 94 * j + 10, 94 * i + 90, 5, 5);
                wchar_t num[10] = L"";
                swprintf_s(num, L"%d", a[i][j]);
                r = { 94 * j - 80, 94 * i, 94 * j + 10, 94 * i + 90 };
                drawtext(num, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
            }
    EndBatchDraw();
}
void move()
{
    memcpy(b, a, sizeof(a));
    memset(mov, false, sizeof(mov));
    char userkey = _getch();
    if (userkey == -32)
        userkey = -_getch();
    switch (userkey)
    {
    case 'w':
    case 'W':
    case -72:
        for (int j = 1; j <= 4; j++)
            for (int i = 2; i <= 4; i++)
            {
                if (!a[i][j])continue;
                int k = i;
                while (!a[k - 1][j] && k >= 2)
                {
                    a[k - 1][j] = a[k][j];
                    a[k][j] = 0;
                    k--;
                }
                if (a[k][j] == a[k - 1][j] && !mov[k - 1][j])
                {
                    a[k - 1][j] = 2 * a[k][j];
                    a[k][j] = 0;
                    mov[k - 1][j] = true;
                    score += a[k - 1][j];
                }
            }
        break;
    case 's':
    case 'S':
    case -80:
        for (int j = 1; j <= 4; j++)
            for (int i = 3; i >= 1; i--)
            {
                if (!a[i][j])continue;
                int k = i;
                while (!a[k + 1][j] && k <= 3)
                {
                    a[k + 1][j] = a[k][j];
                    a[k][j] = 0;
                    k++;
                }
                if (a[k][j] == a[k + 1][j] && !mov[k + 1][j])
                {
                    a[k + 1][j] = 2 * a[k][j];
                    a[k][j] = 0;
                    mov[k + 1][j] = true;
                    score += a[k + 1][j];
                }
            }
        break;
    case 'a':
    case 'A':
    case -75:
        for (int i = 1; i <= 4; i++)
            for (int j = 2; j <= 4; j++)
            {
                if (!a[i][j])continue;
                int k = j;
                while (!a[i][k - 1] && k >= 2)
                {
                    a[i][k - 1] = a[i][k];
                    a[i][k] = 0;
                    k--;
                }
                if (a[i][k] == a[i][k - 1] && !mov[i][k - 1])
                                {
                                    a[i][k - 1] = 2 * a[i][k];
                                    a[i][k] = 0;
                                    mov[i][k - 1] = true;
                                    score += a[i][k - 1];
                                }
                            }
                        break;
                    case 'd':
                    case 'D':
                    case -77:
                        for (int i = 1; i <= 4; i++)
                            for (int j = 3; j >= 1; j--)
                            {
                                if (!a[i][j])continue;
                                int k = j;
                                while (!a[i][k + 1] && k <= 3)
                                {
                                    a[i][k + 1] = a[i][k];
                                    a[i][k] = 0;
                                    k++;
                                }
                                if (a[i][k] == a[i][k + 1] && !mov[i][k + 1])
                                {
                                    a[i][k + 1] = 2 * a[i][k];
                                    a[i][k] = 0;
                                    mov[i][k + 1] = true;
                                    score += a[i][k + 1];
                                }
                            }
                        break;
                    }
                    bool change = false;
                    for (int i = 1; i <= 4; i++)
                        for (int j = 1; j <= 4; j++)
                            if (a[i][j] != b[i][j])
                            {
                                change = true;
                                break;
                            }
                    if (!change)
                        return;
                    int x, y;
                    do
                    {
                        x = rand() % 4 + 1;
                        y = rand() % 4 + 1;
                    } while (a[x][y]);
                    int n = rand() % 6;
                    if (n == 5)a[x][y] = 4;
                    else a[x][y] = 2;
                    best = max(best, score);
                }
                bool gameover()
                ｛for (int i = 1; i <= 4; i++)
                        for (int j = 1; j <= 4; j++)
                            if (!a[i][j] || a[i][j] == a[i + 1][j] || a[i][j] == a[i - 1][j] || a[i][j] == a[i][j + 1] || a[i][j] == a[i][j - 1])return false;
                    return true;
                }
                bool win()
                {
                    for (int i = 1; i <= 4; i++)
                        for (int j = 1; j <= 4; j++)
                            if (a[i][j] == 2048)return true;
                    return false;
                }
                int main()
                {
                    bool ctn = true;
                    initgraph(400, 480);
                    srand((unsigned)time(NULL));
                    while (ctn)
                    {
                        init();
                        drawmap();
                        int endmode = 0;
                        while (1)
                        {
                            move();
                            drawmap();
                            if (win())
                            {
                                endmode = 1;
                                break;
                            }
                            if (gameover())
                            {
                                endmode = 2;
                                break;
                            }
                        }
                        int t;
                        if (endmode == 1)
                            t = MessageBox(0, L"You win!\n再来一局？", L"继续", MB_OKCANCEL);
                        if (endmode == 2)
                            t = MessageBox(0, L"Game over!\n再来一局？", L"继续", MB_OKCANCEL);
                        if (t == IDCANCEL)ctn = false;
                    }
                    closegraph();
                    return 0;
                }
